/*
 * COPYRIGHT:	2010 Christopher Smith, licenced under the GNU GPL v2; see COPYING in the top level directory
 * PROJECT:		sdedit
 * FILE:		acleditor.cpp
 * PURPOSE:		acl editor dialog implementation
 *				includes acl editor *.cpp files
 */

namespace AclEditor
{

HMENU MenuAceTypeStd;
HMENU MenuAceTypeObj;
HMENU MenuAceTypeEx;

HACCEL Accelerator;

static const USHORT AE_LOOKUP_COMPLETED	= WM_USER + 0x100;

//relative column indicies-- each has a listbox and an entry in WindowObject::Columns
static const UCHAR COL_MIN =			0x00;
static const UCHAR COL_MIN_ACE =		COL_MIN + 0x00;
static const UCHAR COL_TSTE_NAME =		COL_MIN_ACE + 0x0;
static const UCHAR COL_TSTE_SID =		COL_MIN_ACE + 0x1;
static const UCHAR COL_OBJ_TYPE =		COL_MIN_ACE + 0x2;
static const UCHAR COL_OBJ_INH_TYPE =	COL_MIN_ACE + 0x3;
static const UCHAR COL_INH_SOURCE =		COL_OBJ_INH_TYPE + 1;
static const UCHAR COL_MAX_VARWIDTH	=	COL_INH_SOURCE;
static const UCHAR COL_ACE_TYPE =		COL_MAX_VARWIDTH + 1;
static const UCHAR COL_MAX_ACE_SEL =	COL_ACE_TYPE;
static const UCHAR COL_ACE_FLAGS =		COL_ACE_TYPE + 1;
static const UCHAR COL_ACE_FLAG_OINH =	COL_ACE_FLAGS + 0;
static const UCHAR COL_ACE_AUDIT_SUCC =	COL_ACE_FLAGS + 6;
static const UCHAR COL_ACE_AUDIT_FAIL =	COL_ACE_FLAGS + 7;
static const UCHAR COL_MAX_ACE_FLAGS =	COL_ACE_FLAGS + 7;
static const UCHAR COL_MASK	=			COL_MAX_ACE_FLAGS + 1;
static const UCHAR COL_SPECIFIC =		COL_MASK;
static const UCHAR COL_MAX_SPECIFIC =	COL_SPECIFIC + 0xF;
static const UCHAR COL_STANDARD =		COL_MAX_SPECIFIC + 0x1;
static const UCHAR COL_STDDELETE =		COL_STANDARD + 0x0;
static const UCHAR COL_STDSYNCH =		COL_STANDARD + 0x4;
static const UCHAR COL_SYSTEM =			COL_STANDARD + 0x8;
static const UCHAR COL_MAX_ALLOWED =	COL_STANDARD + 0x9;
static const UCHAR COL_RESERVE =		COL_STANDARD + 0xA;
static const UCHAR COL_GENERIC =		COL_STANDARD + 0xC;
static const UCHAR COL_MAX_MASK =		COL_MASK + 0x20;
static const UCHAR COL_MAX_ACE =		COL_MAX_MASK;
static const UCHAR COL_MAX =			COL_MAX_ACE;
static const UCHAR COL_SIZE =			COL_MAX + 1;

static const UCHAR TOOLBAR_ID =			COL_MAX + 1;

PWSTR DefaultColumnDescriptions[COL_SIZE];

enum ToolButtonIndex //must be synched with acltoolbar.bmp and acltoolbar_lg.bmp. Used by the toolbar and accelerator
{
	TbOk,
	TbCancel,
	TbReturnNull,
	TbReturnUnspecified,
	TbApply,
	TbShowSid,//relatively aligned with CgTrusteeSid...
	TbShowObject,
	TbShowObjectInherit,
	TbShowInheritSource,
	TbShowSpecific, 
	TbShowStandard,
	TbShowGeneric,
	TbShowExtra, //end alignment with CgTrusteeSid
	TbInsertBefore,
	TbInsertAfter,
	TbShiftUp,
	TbShiftDown,
	TbDelete,
	TbClear,
	TbDefaulted,
	TbProtected,
	TbAutoInherit,
	TbUntrusted,
	TbReinherit,
	TbLoadDefault,
	TbMergeUnprotect,
	TbMergeStart, TbMergeNone = TbMergeStart, //relatively aligned with ACL_MERGE_MODE_*
	TbMergeInhNone,
	TbMergeInhOnly,
	TbMergeInhLast,
	TbMergeInhFirst,
	TbMergeDenyFirst, TbMergeEnd = TbMergeDenyFirst, //end of merge mode align
	TbCount
};

enum ColumnGroups
{
	CgControl,
	CgAclFlags,
	CgTrusteeName,
	CgAceType,
	CgAceFlags,
	CgTrusteeSid,
	CgObjType,
	CgObjInhType,
	CgInhSrc,
	CgSpecific,
	CgStandard,
	CgGeneric,
	CgExtra,
};

BOOLEAN FORCEINLINE IsBitColumn(UCHAR i)
{
	return i <= COL_ACE_FLAGS;
}

class AclEditorCommon;

struct LISTBOX_CTRL //i.e. a column
{
	HWND Wnd; //NULL if non-existant
	int LabelX;	//x position relative to toplabel control
	int Width;
	int WidthFraction; //for variable width columns, the fraction of space devoted to this column
	int PostPadWidth; //size of a pad placed after the column, only shown when visible
	ColumnGroups Group;
	PCWSTR OverheadLabel; //NULL if none
};

struct ListboxAceRow : auto_refctd_std_base
{
	LISTBOX_CTRL *Columns;
	ULONG SidUpdateIndex, TypeUpdateIndex, InhTypeUpdateIndex;
	AclEditorCommon *Container;
	auto_szpod<GUID> TypeGuid;
	auto_szpod<GUID> InhTypeGuid;
	auto_szpod<ACE> OriginalAce;

	ListboxAceRow(AclEditorCommon *Container, LISTBOX_CTRL *Columns, ACE const *OriginalAce) :
		Columns(Columns),
		SidUpdateIndex(0),
		TypeUpdateIndex(0),
		InhTypeUpdateIndex(0),
		Container(Container),
		OriginalAce(OriginalAce)
	{}
};

#include "toplabelctl.cpp"

struct AclEditorInitParams
{
	SDE_GUI_PREFS Prefs;
	HWND Parent;
	PCWSTR const *Headers;
	PCWSTR Title;
	ACL_AND_STATE const &AclAndState;
	ULONG SdState;
	DIALOG_CALLBACK_PROC CallbackProc;
	PVOID CallbackContext;
	Lookup::Translators *Translators;
	Lookup::Enumerators *Enumerators;
	auto_array<auto_szpod<WCHAR> > *PathParts;

	AclEditorInitParams(SDE_GUI_PREFS Prefs, HWND Parent, PCWSTR Title, PCWSTR const *Headers, ACL_AND_STATE const &AclAndState, ULONG SdState, Lookup::Translators *Translators, Lookup::Enumerators *Enumerators, auto_array<auto_szpod<WCHAR> > *PathParts, DIALOG_CALLBACK_PROC CallbackProc, PVOID CallbackContext) :
		Prefs(Prefs),
		Parent(Parent),
		Title(Title),
		Headers(Headers),
		AclAndState(AclAndState),
		SdState(SdState),
		Translators(Translators),
		CallbackProc(CallbackProc),
		CallbackContext(CallbackContext),
		Enumerators(Enumerators),
		PathParts(PathParts)
	{}

	AclEditorInitParams &operator =(AclEditorInitParams const &); //lifetime strictly controlled: no copying possible
};

struct WindowClassLifetime;

class AclEditorCommon : public ClassedWindowBase
{
friend WindowClassLifetime;

public:
	SDE_GUI_PREFS Prefs;
	LISTBOX_CTRL Columns[COL_SIZE];
	auto_array<ListboxAceRow *> Rows;
	USHORT RowMax;
	auto_refct<TopLabel::WindowObject> TopLabels;
	BOOLEAN ShowExtras;
	DialogCallback Callback;
	ULONG PreviousAclState;
	ULONG SdState;
	HWND Toolbar;
	auto_array<auto_szpod<WCHAR> > PathParts;

	AclEditorCommon(AclEditorInitParams const &Init) :
		Callback(Init.CallbackProc, Init.CallbackContext),
		Prefs(Init.Prefs),
		RowMax(MAXUSHORT),
		ShowExtras(FALSE),
		PathParts(*Init.PathParts)
	{}
};

#include "acleditor init class.cpp"

#include "acleditor columns.cpp"

#include "acleditor rows.cpp"

#include "acleditor lookup.cpp"

#include "acleditor editpopup.cpp"

#include "acleditor init.cpp"

#include "acleditor load.cpp"

#include "acleditor save.cpp"

#include "acleditor command.cpp"

//inheritance hierarchy accumlates components in this order:
//AclEditorColumns, AclEditorRows, AclEditorEditPopup, AclEditorInit, AclEditorLookup, AclEditorLoad, AclEditorSave, AclEditorCommand
//each component depends only on AclEditorCommon or previous components

struct AclEditor : AclEditorCommand
{
	AclEditor(SDE_GUI_PREFS Prefs, HWND Parent, PWSTR Title, PCWSTR const *Headers, ACL_AND_STATE const &AclAndState, ULONG SdState, Lookup::Translators *Translators, Lookup::Enumerators *Enumerators, auto_array<auto_szpod<WCHAR> > *PathParts, DIALOG_CALLBACK_PROC CallbackProc, PVOID CallbackContext) :
		AclEditorCommand(AclEditorInitParams(Prefs, Parent, Title, Headers, AclAndState, SdState, Translators, Enumerators, PathParts, CallbackProc, CallbackContext))
	{}
};

}//namespace AclEditor